import sys
import os
import time
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QLabel, QLineEdit, QPushButton, QFileDialog, QTextEdit, 
                             QFrame, QComboBox, QGridLayout, QGroupBox, QMessageBox, 
                             QScrollArea, QStatusBar)
from PySide6.QtCore import Qt, QThread, Signal, QObject, Slot
from PySide6.QtGui import QFont, QTextCursor

class FilterRuleWidget(QWidget):
    """过滤规则组件，用于显示和编辑单条过滤规则"""
    remove_requested = Signal(object)  # 移除规则信号
    
    def __init__(self, index, parent=None):
        super().__init__(parent)
        self.index = index
        self.init_ui()
        
    def init_ui(self):
        layout = QHBoxLayout(self)
        layout.setContentsMargins(2, 2, 2, 2)
        
        # 序号标签
        self.index_label = QLabel(str(self.index + 1))
        self.index_label.setFixedWidth(30)
        self.index_label.setAlignment(Qt.AlignCenter)
        
        # 规则类型下拉框
        self.logic_combo = QComboBox()
        self.logic_combo.addItems(["包含", "不包含"])
        self.logic_combo.setFixedWidth(80)
        
        # 关键词输入框
        self.text_edit = QLineEdit()
        self.text_edit.setPlaceholderText("输入关键词")
        
        # 删除按钮
        self.remove_btn = QPushButton("删除")
        self.remove_btn.setFixedWidth(50)
        self.remove_btn.clicked.connect(self.on_remove_clicked)
        
        # 添加组件到布局
        layout.addWidget(self.index_label)
        layout.addWidget(self.logic_combo)
        layout.addWidget(self.text_edit)
        layout.addWidget(self.remove_btn)
        
    def on_remove_clicked(self):
        """发送移除规则请求"""
        self.remove_requested.emit(self)
        
    def update_index(self, new_index):
        """更新序号显示"""
        self.index = new_index
        self.index_label.setText(str(new_index + 1))
        
    def get_rule(self):
        """获取规则数据"""
        return {
            "logic": self.logic_combo.currentText(),
            "text": self.text_edit.text().strip()
        }

class SplitWorker(QObject):
    """拆分工作线程，在后台执行文件写入操作"""
    progress_updated = Signal(int, int, str)  # 当前进度, 总进度, 评论预览
    finished = Signal(str, int)  # 输出目录, 总数量
    canceled = Signal()
    error_occurred = Signal(str)  # 错误信息
    
    def __init__(self, output_dir, comments):
        super().__init__()
        self.output_dir = output_dir
        self.comments = comments
        self.is_running = True
        self.is_canceled = False
        
    @Slot()
    def run(self):
        """执行拆分任务"""
        try:
            main_dir = os.path.join(self.output_dir, "评价文本集合")
            os.makedirs(main_dir, exist_ok=True)
            
            total = len(self.comments)
            
            for idx, comment in enumerate(self.comments, 1):
                # 检查是否需要取消
                if self.is_canceled:
                    self.canceled.emit()
                    return
                    
                # 检查是否需要停止
                if not self.is_running:
                    return
                    
                # 创建子目录和文件
                sub_dir = os.path.join(main_dir, f"评价_{idx:03d}")
                os.makedirs(sub_dir, exist_ok=True)
                
                file_path = os.path.join(sub_dir, "comment.txt")
                with open(file_path, "w", encoding="utf-8") as f:
                    f.write(comment)
                    
                # 发送进度更新
                preview = comment[:30] + "..." if len(comment) > 30 else comment
                self.progress_updated.emit(idx, total, preview)
                
                # 短暂休眠，降低CPU占用
                time.sleep(0.01)
                
            # 完成任务
            self.finished.emit(main_dir, total)
            
        except Exception as e:
            self.error_occurred.emit(str(e))
    
    def cancel(self):
        """取消任务"""
        self.is_canceled = True
        
    def stop(self):
        """停止任务"""
        self.is_running = False

class CommentSplitterWindow(QMainWindow):
    """主窗口类"""
    def __init__(self):
        super().__init__()
        self.comments = []
        self.filtered_comments = []
        self.filter_rules = []
        self.split_thread = None
        self.split_worker = None
        
        self.init_ui()
        
    def init_ui(self):
        """初始化界面"""
        # 设置窗口属性
        self.setWindowTitle("评价拆分工具")
        self.setGeometry(100, 100, 700, 600)
        self.setMinimumSize(600, 550)
        
        # 设置字体
        font = QFont("微软雅黑", 9)
        self.setFont(font)
        
        # 创建中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(15, 15, 15, 15)
        main_layout.setSpacing(10)
        
        # 标题
        title_label = QLabel("评价拆分工具")
        title_font = QFont("微软雅黑", 12, QFont.Bold)
        title_label.setFont(title_font)
        main_layout.addWidget(title_label)
        
        # 输入区域
        input_group = QGroupBox("输入设置")
        input_layout = QVBoxLayout(input_group)
        
        # 评价文件选择
        file_layout = QHBoxLayout()
        self.file_path_edit = QLineEdit()
        self.file_path_edit.setReadOnly(True)
        browse_file_btn = QPushButton("浏览...")
        browse_file_btn.clicked.connect(self.select_comment_file)
        
        file_layout.addWidget(QLabel("评价文件:"))
        file_layout.addWidget(self.file_path_edit, 1)
        file_layout.addWidget(browse_file_btn)
        
        # 输出目录选择
        output_layout = QHBoxLayout()
        self.output_path_edit = QLineEdit()
        self.output_path_edit.setReadOnly(True)
        browse_output_btn = QPushButton("浏览...")
        browse_output_btn.clicked.connect(self.select_output_path)
        
        output_layout.addWidget(QLabel("输出目录:"))
        output_layout.addWidget(self.output_path_edit, 1)
        output_layout.addWidget(browse_output_btn)
        
        input_layout.addLayout(file_layout)
        input_layout.addLayout(output_layout)
        main_layout.addWidget(input_group)
        
        # 过滤规则区域
        filter_group = QGroupBox("过滤规则（所有规则需同时满足）")
        filter_layout = QVBoxLayout(filter_group)
        
        # 滚动区域用于容纳多个过滤规则
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_content = QWidget()
        self.rules_layout = QVBoxLayout(self.scroll_content)
        self.rules_layout.setSpacing(5)
        self.scroll_area.setWidget(self.scroll_content)
        
        # 添加规则按钮
        add_rule_btn = QPushButton("添加规则")
        add_rule_btn.clicked.connect(self.add_filter_rule)
        
        # 应用过滤按钮
        apply_filter_btn = QPushButton("应用过滤")
        apply_filter_btn.clicked.connect(self.apply_filter)
        
        # 按钮布局
        btn_layout = QHBoxLayout()
        btn_layout.addWidget(add_rule_btn)
        btn_layout.addStretch(1)
        btn_layout.addWidget(apply_filter_btn)
        
        # 说明文字
        info_label = QLabel("说明：规则之间为逻辑与关系，即需同时满足所有规则。例如规则1选“包含A”、规则2选“不包含B”，则保留同时符合的评价。")
        info_label.setWordWrap(True)
        info_label.setStyleSheet("color: #666; font-size: 8pt;")
        
        filter_layout.addWidget(self.scroll_area)
        filter_layout.addLayout(btn_layout)
        filter_layout.addWidget(info_label)
        main_layout.addWidget(filter_group)
        
        # 预览区域
        preview_group = QGroupBox("评价预览")
        preview_layout = QVBoxLayout(preview_group)
        self.preview_text = QTextEdit()
        self.preview_text.setReadOnly(True)
        preview_layout.addWidget(self.preview_text)
        main_layout.addWidget(preview_group)
        
        # 操作按钮区域
        btn_group_layout = QHBoxLayout()
        
        self.load_btn = QPushButton("加载评价")
        self.load_btn.clicked.connect(self.load_comments)
        
        self.split_btn = QPushButton("拆分评价")
        self.split_btn.clicked.connect(self.start_split)
        
        self.cancel_btn = QPushButton("取消")
        self.cancel_btn.clicked.connect(self.cancel_split)
        self.cancel_btn.setEnabled(False)
        
        btn_group_layout.addWidget(self.load_btn)
        btn_group_layout.addStretch(1)
        btn_group_layout.addWidget(self.cancel_btn)
        btn_group_layout.addWidget(self.split_btn)
        
        main_layout.addLayout(btn_group_layout)
        
        # 状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage("就绪")
        
        # 添加初始规则
        self.add_filter_rule()
    
    def add_filter_rule(self):
        """添加一条新的过滤规则"""
        rule_widget = FilterRuleWidget(len(self.filter_rules), self)
        rule_widget.remove_requested.connect(self.remove_filter_rule)
        self.filter_rules.append(rule_widget)
        self.rules_layout.addWidget(rule_widget)
        self.update_rule_indices()
    
    def remove_filter_rule(self, rule_widget):
        """移除一条过滤规则"""
        if len(self.filter_rules) > 1:  # 至少保留一条规则
            self.filter_rules.remove(rule_widget)
            self.rules_layout.removeWidget(rule_widget)
            rule_widget.deleteLater()
            self.update_rule_indices()
    
    def update_rule_indices(self):
        """更新所有规则的序号"""
        for i, rule_widget in enumerate(self.filter_rules):
            rule_widget.update_index(i)
    
    def select_comment_file(self):
        """选择评价文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择评价文件", "", "文本文件 (*.txt);;所有文件 (*)"
        )
        if file_path:
            self.file_path_edit.setText(file_path)
    
    def select_output_path(self):
        """选择输出目录"""
        dir_path = QFileDialog.getExistingDirectory(
            self, "选择输出目录", os.path.expanduser("~")
        )
        if dir_path:
            self.output_path_edit.setText(dir_path)
    
    def load_comments(self):
        """加载评价文件"""
        file_path = self.file_path_edit.text()
        if not file_path or not os.path.exists(file_path):
            QMessageBox.critical(self, "错误", "请选择有效的评价文件！")
            return
        
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                self.comments = [line.strip() for line in f if line.strip()]
            
            self.filtered_comments = self.comments.copy()
            self.update_preview()
            self.statusBar.showMessage(f"已加载 {len(self.comments)} 条评价")
            QMessageBox.information(self, "成功", f"已加载 {len(self.comments)} 条有效评价！")
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"加载失败：{str(e)}")
            self.statusBar.showMessage("加载失败")
    
    def apply_filter(self):
        """应用过滤规则"""
        if not self.comments:
            QMessageBox.warning(self, "提示", "请先加载评价文件！")
            return
        
        # 收集有效规则
        valid_rules = []
        for rule_widget in self.filter_rules:
            rule = rule_widget.get_rule()
            if rule["text"]:  # 忽略空规则
                valid_rules.append(rule)
        
        if not valid_rules:
            self.filtered_comments = self.comments.copy()
            self.statusBar.showMessage("无有效规则，显示全部评价")
            self.update_preview()
            return
        
        # 应用所有规则（逻辑与）
        self.filtered_comments = []
        for comment in self.comments:
            match_all = True
            for rule in valid_rules:
                if rule["logic"] == "包含":
                    if rule["text"] not in comment:
                        match_all = False
                        break
                else:  # 不包含
                    if rule["text"] in comment:
                        match_all = False
                        break
            if match_all:
                self.filtered_comments.append(comment)
        
        # 更新状态和预览
        rule_desc = "; ".join([f"{r['logic']}{r['text']}" for r in valid_rules])
        self.statusBar.showMessage(
            f"过滤完成！共 {len(self.filtered_comments)} 条符合条件的评价（规则：{rule_desc}）"
        )
        self.update_preview()
    
    def update_preview(self):
        """更新预览区域"""
        self.preview_text.clear()
        display_limit = 10
        
        for i, comment in enumerate(self.filtered_comments[:display_limit], 1):
            self.preview_text.append(f"{i}. {comment}\n")
        
        if len(self.filtered_comments) > display_limit:
            self.preview_text.append(f"... 还有 {len(self.filtered_comments) - display_limit} 条未显示 ...")
            
        # 滚动到底部 - 修复此处的属性错误
        cursor = self.preview_text.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.preview_text.setTextCursor(cursor)
    
    def start_split(self):
        """开始拆分评价（多线程）"""
        output_dir = self.output_path_edit.text()
        if not output_dir:
            QMessageBox.critical(self, "错误", "请选择输出目录！")
            return
        
        if not self.filtered_comments:
            QMessageBox.critical(self, "错误", "无有效评价可拆分！")
            return
        
        # 检查是否已有线程在运行
        if self.split_thread and self.split_thread.isRunning():
            QMessageBox.information(self, "提示", "拆分正在进行中，请等待完成或取消当前操作")
            return
        
        # 初始化线程和工作对象
        self.split_worker = SplitWorker(output_dir, self.filtered_comments)
        self.split_thread = QThread()
        
        # 连接信号槽
        self.split_worker.progress_updated.connect(self.update_split_progress)
        self.split_worker.finished.connect(self.split_finished)
        self.split_worker.canceled.connect(self.split_canceled)
        self.split_worker.error_occurred.connect(self.split_error)
        
        # 移动工作对象到线程并启动
        self.split_worker.moveToThread(self.split_thread)
        self.split_thread.started.connect(self.split_worker.run)
        self.split_thread.finished.connect(self.split_worker.stop)
        
        # 更新UI状态
        self.split_btn.setEnabled(False)
        self.cancel_btn.setEnabled(True)
        self.load_btn.setEnabled(False)
        self.statusBar.showMessage("准备开始拆分...")
        self.preview_text.clear()
        
        # 启动线程
        self.split_thread.start()
    
    def update_split_progress(self, current, total, preview):
        """更新拆分进度"""
        self.statusBar.showMessage(f"正在拆分：{current}/{total}")
        self.preview_text.append(f"已保存：评价_{current:03d}\n{preview}\n")
        
        # 滚动到底部 - 修复此处的属性错误
        cursor = self.preview_text.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.preview_text.setTextCursor(cursor)
    
    def split_finished(self, output_dir, total):
        """拆分完成处理"""
        self.statusBar.showMessage(f"拆分完成！共生成 {total} 个文件夹")
        self.cleanup_split_thread()
        QMessageBox.information(self, "成功", f"已拆分至：\n{output_dir}\n共 {total} 条评价")
    
    def split_canceled(self):
        """拆分取消处理"""
        self.statusBar.showMessage("拆分已取消")
        self.cleanup_split_thread()
        QMessageBox.information(self, "提示", "拆分操作已取消")
    
    def split_error(self, error_msg):
        """拆分错误处理"""
        self.statusBar.showMessage("拆分失败")
        self.cleanup_split_thread()
        QMessageBox.critical(self, "错误", f"拆分失败：{error_msg}")
    
    def cancel_split(self):
        """取消拆分操作"""
        if self.split_worker and self.split_thread and self.split_thread.isRunning():
            self.split_worker.cancel()
            self.statusBar.showMessage("正在取消...")
            self.cancel_btn.setEnabled(False)
    
    def cleanup_split_thread(self):
        """清理拆分线程资源"""
        if self.split_thread and self.split_thread.isRunning():
            self.split_thread.quit()
            self.split_thread.wait()
        
        self.split_thread = None
        self.split_worker = None
        
        # 恢复UI状态
        self.split_btn.setEnabled(True)
        self.cancel_btn.setEnabled(False)
        self.load_btn.setEnabled(True)
    
    def closeEvent(self, event):
        """窗口关闭事件处理"""
        if self.split_thread and self.split_thread.isRunning():
            reply = QMessageBox.question(
                self, "提示", "拆分正在进行中，确定要关闭窗口吗？",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No
            )
            if reply == QMessageBox.Yes:
                if self.split_worker:
                    self.split_worker.stop()
                self.split_thread.quit()
                self.split_thread.wait()
                event.accept()
            else:
                event.ignore()
        else:
            event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = CommentSplitterWindow()
    window.show()
    sys.exit(app.exec())
    